package com.zhouxiaoxuan13.promotionservice.controller;

import brave.Span;
import brave.Tracer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 链路跟踪测试控制器
 * 用于演示Zipkin分布式链路跟踪功能
 */
@Slf4j
@RestController
@RequestMapping("/api/tracing")
@CrossOrigin(origins = "*")
public class TracingController {

    @Autowired
    private Tracer tracer;

    @Value("${server.port}")
    private String serverPort;

    @Value("${spring.application.name}")
    private String applicationName;

    private final Random random = new Random();

    /**
     * 基础链路跟踪测试
     */
    @GetMapping("/basic")
    public ResponseEntity<Map<String, Object>> basicTracing() {
        log.info("=== 基础链路跟踪测试开始 ===");

        // 创建自定义Span
        Span customSpan = tracer.nextSpan()
                .name("basic-tracing-operation")
                .tag("service.name", applicationName)
                .tag("service.port", serverPort)
                .tag("operation.type", "basic-test")
                .start();

        try (Tracer.SpanInScope ws = tracer.withSpanInScope(customSpan)) {
            // 模拟业务处理
            simulateBusinessLogic("基础链路跟踪", 100, 300);

            Map<String, Object> response = createResponse("基础链路跟踪测试");
            response.put("traceId", customSpan.context().traceId());
            response.put("spanId", customSpan.context().spanId());

            log.info("=== 基础链路跟踪测试完成 ===");
            return ResponseEntity.ok(response);

        } finally {
            customSpan.finish();
        }
    }

    /**
     * 复杂链路跟踪测试（包含多个子操作）
     */
    @GetMapping("/complex")
    public ResponseEntity<Map<String, Object>> complexTracing() {
        log.info("=== 复杂链路跟踪测试开始 ===");

        Span mainSpan = tracer.nextSpan()
                .name("complex-tracing-operation")
                .tag("service.name", applicationName)
                .tag("service.port", serverPort)
                .tag("operation.type", "complex-test")
                .start();

        try (Tracer.SpanInScope ws = tracer.withSpanInScope(mainSpan)) {
            // 第一个子操作：数据查询
            performSubOperation("data-query", "数据查询操作", 50, 150);

            // 第二个子操作：业务处理
            performSubOperation("business-processing", "业务处理操作", 100, 200);

            // 第三个子操作：结果封装
            performSubOperation("result-packaging", "结果封装操作", 30, 80);

            Map<String, Object> response = createResponse("复杂链路跟踪测试");

            // 获取当前Span信息
            Span currentSpan = tracer.currentSpan();
            if (currentSpan != null) {
                response.put("traceId", currentSpan.context().traceId());
                response.put("spanId", currentSpan.context().spanId());
            }

            log.info("=== 复杂链路跟踪测试完成 ===");
            return ResponseEntity.ok(response);
        } finally {
            mainSpan.finish();
        }
    }

    /**
     * 错误链路跟踪测试
     */
    @GetMapping("/error")
    public ResponseEntity<Map<String, Object>> errorTracing() {
        log.info("=== 错误链路跟踪测试开始 ===");
        
        Span errorSpan = tracer.nextSpan()
                .name("error-tracing-operation")
                .tag("service.name", applicationName)
                .tag("service.port", serverPort)
                .tag("operation.type", "error-test")
                .start();

        try (Tracer.SpanInScope ws = tracer.withSpanInScope(errorSpan)) {
            // 模拟业务处理
            simulateBusinessLogic("错误链路跟踪", 50, 100);
            
            // 模拟错误情况
            if (random.nextBoolean()) {
                RuntimeException error = new RuntimeException("模拟的业务异常");
                errorSpan.tag("error", "true")
                        .tag("error.message", error.getMessage())
                        .tag("error.type", error.getClass().getSimpleName());
                
                log.error("模拟业务异常发生", error);
                
                Map<String, Object> errorResponse = createResponse("错误链路跟踪测试（异常情况）");
                errorResponse.put("error", true);
                errorResponse.put("errorMessage", error.getMessage());
                errorResponse.put("traceId", errorSpan.context().traceId());
                errorResponse.put("spanId", errorSpan.context().spanId());
                
                return ResponseEntity.status(500).body(errorResponse);
            }
            
            Map<String, Object> response = createResponse("错误链路跟踪测试（正常情况）");
            response.put("traceId", errorSpan.context().traceId());
            response.put("spanId", errorSpan.context().spanId());
            
            log.info("=== 错误链路跟踪测试完成（正常情况） ===");
            return ResponseEntity.ok(response);
            
        } finally {
            errorSpan.finish();
        }
    }

    /**
     * 获取当前链路信息
     */
    @GetMapping("/current")
    public ResponseEntity<Map<String, Object>> getCurrentTracing() {
        Map<String, Object> response = createResponse("当前链路信息");
        
        Span currentSpan = tracer.currentSpan();
        if (currentSpan != null) {
            response.put("hasActiveTrace", true);
            response.put("traceId", currentSpan.context().traceId());
            response.put("spanId", currentSpan.context().spanId());
        } else {
            response.put("hasActiveTrace", false);
            response.put("message", "当前没有活跃的链路跟踪");
        }
        
        return ResponseEntity.ok(response);
    }

    /**
     * 执行子操作
     */
    private void performSubOperation(String operationName, String description, int minDelay, int maxDelay) {
        Span subSpan = tracer.nextSpan()
                .name(operationName)
                .tag("operation.description", description)
                .tag("service.name", applicationName)
                .start();

        try (Tracer.SpanInScope ws = tracer.withSpanInScope(subSpan)) {
            log.info("执行子操作: {}", description);
            simulateBusinessLogic(description, minDelay, maxDelay);
            subSpan.tag("operation.status", "success");
        } catch (Exception e) {
            subSpan.tag("error", "true")
                   .tag("error.message", e.getMessage());
            throw e;
        } finally {
            subSpan.finish();
        }
    }

    /**
     * 模拟业务逻辑处理
     */
    private void simulateBusinessLogic(String operation, int minDelay, int maxDelay) {
        try {
            int delay = random.nextInt(maxDelay - minDelay + 1) + minDelay;
            log.info("模拟 {} 处理，耗时: {}ms", operation, delay);
            TimeUnit.MILLISECONDS.sleep(delay);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("操作被中断", e);
        }
    }

    /**
     * 创建响应对象
     */
    private Map<String, Object> createResponse(String operation) {
        Map<String, Object> response = new HashMap<>();
        response.put("operation", operation);
        response.put("serviceName", applicationName);
        response.put("servicePort", serverPort);
        response.put("timestamp", LocalDateTime.now());
        response.put("success", true);
        return response;
    }
}
